package redis

import (
	"errors"
	"github.com/go-redis/redis"
	"go.uber.org/zap"
	"math"
	"strconv"
	"time"
)

const (
	oneWeekInSeconds = 7 * 24 * 3600
	scorePerVote     = 432 // 每一票的分数
)

var (
	ErrVoteTimeExpire = errors.New("不能挖坟！")
)

func PostVote(userId, postID string, direction float64) error {
	// 判断投票限制
	// 查询该 帖子 key 下的 某个帖子的时间
	postTime := rdb.ZScore(KeyPostTimeZSet, postID).Val()
	if float64(time.Now().Unix())-postTime > oneWeekInSeconds {
		return ErrVoteTimeExpire
	}

	// 查询当前用户为此帖子的投票记录
	ov := rdb.ZScore(KeyPostVoted+postID, userId).Val()
	// 计算差值绝对值
	var diff float64
	if direction > ov {
		diff = 1 * math.Abs(ov-direction) * scorePerVote
	} else {
		diff = -1 * math.Abs(ov-direction) * scorePerVote
	}

	// 更新此帖子的分数 和 更新用户对此贴子的投票记录应该放在一个事务里

	pipeline := rdb.TxPipeline()

	// 更新分数
	pipeline.ZIncrBy(KeyPostScoreZSet, diff, postID)
	//if err != nil {
	//	return err
	//}
	// 修改此贴子对应此用户的投票状态， 0 移除
	if direction == 0 {
		pipeline.ZRem(KeyPostVoted+postID, userId)

	}
	rdb.ZAdd(KeyPostVoted+postID, redis.Z{
		Score:  direction,
		Member: userId,
	})

	_, err := pipeline.Exec()
	if err != nil {
		zap.L().Error("投票失败！redis", zap.Error(err))
		return err
	}
	return nil

}

func CreatePost(pid int64, cid int64) (err error) {
	// 事务操作
	pipeline := rdb.TxPipeline()

	// 新建的帖子，将其存到 redis  KeyPostTimeZSet
	pipeline.ZAdd(KeyPostTimeZSet, redis.Z{
		Score:  float64(time.Now().Unix()),
		Member: pid,
	})
	//if err != nil {
	//	zap.L().Error("rdb.ZAdd failed", zap.Error(err))
	//	return
	//}

	// 同时 帖子的评分也需要创建伊始时间作为 其权重值

	pipeline.ZAdd(KeyPostScoreZSet, redis.Z{
		Score:  float64(time.Now().Unix()),
		Member: pid,
	})

	// 每次创建一个新的帖子，需要在redis中存储起来
	pipeline.SAdd(KeyCommunitySet+strconv.Itoa(int(cid)), pid)

	_, err = pipeline.Exec()

	if err != nil {
		zap.L().Error("创建帖子在redis中出现错误", zap.Error(err))
		return
	}

	return
}
